@tool
extends EditorPlugin

const PACK_SCRIPT = "res://addons/deb_packager/pack_deb.sh"

# 进度对话框类
class ProgressDialog extends AcceptDialog:
	var progress_bar: ProgressBar
	var log_output: TextEdit
	var cancel_btn: Button
	var process_id: int = -1
	var output_file: FileAccess
	var output_path: String
	
	func _init():
		title = "Building DEB Package"
		min_size = Vector2(500, 300)
		
		var vbox = VBoxContainer.new()
		vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
		add_child(vbox)
		
		# 进度条
		progress_bar = ProgressBar.new()
		progress_bar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
		progress_bar.min_value = 0
		progress_bar.max_value = 100
		vbox.add_child(progress_bar)
		
		# 日志输出
		log_output = TextEdit.new()
		log_output.size_flags_vertical = Control.SIZE_EXPAND_FILL
		log_output.editable = false
		log_output.scroll_following = true
		log_output.syntax_highlighting = true
		vbox.add_child(log_output)
		
		# 按钮区域
		var btn_hbox = HBoxContainer.new()
		vbox.add_child(btn_hbox)
		
		cancel_btn = Button.new()
		cancel_btn.text = "Cancel"
		cancel_btn.connect("pressed", self._on_cancel_pressed)
		btn_hbox.add_child(cancel_btn)
		
		var spacer = Control.new()
		spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
		btn_hbox.add_child(spacer)
	
	func _on_cancel_pressed():
		if process_id != -1:
			OS.kill(process_id)
			log_output.text += "\n[!] Process cancelled by user\n"
			cancel_btn.disabled = true
		if output_file != null:
			output_file.close()
			output_file = null
	
	func add_log(text: String):
		log_output.text += text + "\n"
		# 自动滚动到底部
		log_output.scroll_vertical = log_output.get_line_count() - 1
	
	func update_progress(value: float):
		progress_bar.value = value
	
	# 创建输出文件用于捕获进程输出
	func create_output_file():
		output_path = OS.get_cache_dir() + "/godot_deb_output_%s.txt" % Time.get_unix_time_from_system()
		output_file = FileAccess.open(output_path, FileAccess.WRITE)
		return output_file != null
	
	# 读取新的输出内容
	func read_new_output():
		if output_path == null:
			return []
		
		var read_file = FileAccess.open(output_path, FileAccess.READ)
		if read_file == null:
			return []
		
		var new_lines = []
		while not read_file.eof_reached():
			var line = read_file.get_line()
			if line != "":
				new_lines.append(line)
		
		read_file.close()
		return new_lines

func _enter_tree():
	add_tool_menu_item("Package to DEB", _package_to_deb)

func _exit_tree():
	remove_tool_menu_item("Package to DEB")

func _package_to_deb():
	# 创建配置对话框
	var dialog = AcceptDialog.new()
	dialog.title = "DEB Packaging"
	dialog.min_size = Vector2(400, 300)
	
	var vbox = VBoxContainer.new()
	dialog.add_child(vbox)
	
	# 可执行文件选择器
	var exec_hbox = HBoxContainer.new()
	vbox.add_child(exec_hbox)
	
	var exec_label = Label.new()
	exec_label.text = "Executable:"
	exec_hbox.add_child(exec_label)
	
	var exec_entry = LineEdit.new()
	exec_entry.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	exec_hbox.add_child(exec_entry)
	
	var exec_btn = Button.new()
	exec_btn.text = "Browse"
	exec_btn.connect("pressed", _browse_file.bind(exec_entry))
	exec_hbox.add_child(exec_btn)
	
	# 输出目录选择器
	var out_hbox = HBoxContainer.new()
	vbox.add_child(out_hbox)
	
	var out_label = Label.new()
	out_label.text = "Output Directory:"
	out_hbox.add_child(out_label)
	
	var out_entry = LineEdit.new()
	out_entry.text = "res://"
	out_entry.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	out_hbox.add_child(out_entry)
	
	var out_btn = Button.new()
	out_btn.text = "Browse"
	out_btn.connect("pressed", _browse_folder.bind(out_entry))
	out_hbox.add_child(out_btn)
	
	# 包信息
	var name_hbox = HBoxContainer.new()
	vbox.add_child(name_hbox)
	
	var name_label = Label.new()
	name_label.text = "Package Name:"
	name_hbox.add_child(name_label)
	
	var name_entry = LineEdit.new()
	name_entry.text = ProjectSettings.get_setting("application/config/name")
	name_hbox.add_child(name_entry)
	
	var ver_hbox = HBoxContainer.new()
	vbox.add_child(ver_hbox)
	
	var ver_label = Label.new()
	ver_label.text = "Version:"
	ver_hbox.add_child(ver_label)
	
	var ver_entry = LineEdit.new()
	ver_entry.text = "1.0.0"
	ver_hbox.add_child(ver_entry)
	
	# 架构选择
	var arch_hbox = HBoxContainer.new()
	vbox.add_child(arch_hbox)
	
	var arch_label = Label.new()
	arch_label.text = "Architecture:"
	arch_hbox.add_child(arch_label)
	
	var arch_option = OptionButton.new()
	arch_option.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	arch_option.add_item("any (Multi-Arch)", 0)
	arch_option.add_item("amd64", 1)
	arch_option.add_item("arm64", 2)
	arch_option.add_item("armhf", 3)
	arch_option.add_item("i386", 4)
	arch_option.select(0)  # 默认选择any
	arch_hbox.add_child(arch_option)
	
	# 描述信息
	var desc_hbox = HBoxContainer.new()
	vbox.add_child(desc_hbox)
	
	var desc_label = Label.new()
	desc_label.text = "Description:"
	desc_hbox.add_child(desc_label)
	
	var desc_entry = LineEdit.new()
	desc_entry.text = ProjectSettings.get_setting("application/config/description", "Godot Game")
	desc_entry.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	desc_hbox.add_child(desc_entry)
	
	# 确认按钮
	var confirm_btn = Button.new()
	confirm_btn.text = "Build DEB"
	confirm_btn.connect("pressed", _run_packaging.bind({
		"exec": exec_entry,
		"output": out_entry,
		"name": name_entry,
		"version": ver_entry,
		"arch": arch_option,
		"desc": desc_entry,
		"dialog": dialog
	}))
	vbox.add_child(confirm_btn)
	
	# 显示对话框
	get_editor_interface().get_base_control().add_child(dialog)
	dialog.popup_centered()

func _browse_file(entry):
	var fd = EditorFileDialog.new()
	fd.file_mode = EditorFileDialog.FILE_MODE_OPEN_FILE
	fd.access = EditorFileDialog.ACCESS_FILESYSTEM
	fd.connect("file_selected", func(path): entry.text = path)
	get_editor_interface().get_base_control().add_child(fd)
	fd.popup_centered_ratio(0.7)

func _browse_folder(entry):
	var fd = EditorFileDialog.new()
	fd.file_mode = EditorFileDialog.FILE_MODE_OPEN_DIR
	fd.access = EditorFileDialog.ACCESS_FILESYSTEM
	fd.connect("dir_selected", func(path): entry.text = path)
	get_editor_interface().get_base_control().add_child(fd)
	fd.popup_centered_ratio(0.7)

func _run_packaging(params):
	var exec_path = params.exec.text
	var output_dir = params.output.text
	var pkg_name = params.name.text
	var version = params.version.text
	var architecture = params.arch.get_item_text(params.arch.get_selected_id())
	var description = params.desc.text
	
	# 验证输入
	if exec_path.is_empty() or output_dir.is_empty() or pkg_name.is_empty() or version.is_empty():
		push_error("All fields are required!")
		return
	
	# 关闭配置对话框
	params.dialog.queue_free()
	
	# 创建进度对话框
	var progress_dialog = ProgressDialog.new()
	get_editor_interface().get_base_control().add_child(progress_dialog)
	progress_dialog.popup_centered()
	
	# 转换为绝对路径
	exec_path = ProjectSettings.globalize_path(exec_path)
	output_dir = ProjectSettings.globalize_path(output_dir)
	var script_path = ProjectSettings.globalize_path(PACK_SCRIPT)
	
	# 设置进度条初始状态
	progress_dialog.update_progress(0)
	progress_dialog.add_log("Starting DEB packaging process...")
	progress_dialog.add_log("Target architecture: " + architecture)
	
	# 创建输出文件
	if not progress_dialog.create_output_file():
		progress_dialog.add_log("ERROR: Failed to create output log file")
		return
	
	# 执行打包脚本（重定向输出到文件）
	var args = [script_path, exec_path, output_dir, pkg_name, version, architecture, description]
	var process_id = OS.create_process("bash", args, true)
	
	if process_id <= 0:
		progress_dialog.add_log("ERROR: Failed to start packaging process")
		return
	
	progress_dialog.process_id = process_id
	
	# 设置计时器监控进度
	var timer = Timer.new()
	timer.wait_time = 0.5  # 检查间隔
	timer.connect("timeout", _monitor_process.bind(progress_dialog, timer))
	get_editor_interface().get_base_control().add_child(timer)
	timer.start()

# 监控进程状态的函数
func _monitor_process(progress_dialog, timer):
	# 检查进程状态
	var process_running = OS.is_process_running(progress_dialog.process_id)
	
	# 读取新的输出内容
	var new_lines = progress_dialog.read_new_output()
	for line in new_lines:
		if line.begins_with("[PROGRESS]"):
			var progress_text = line.substr(11).strip_edges()
			progress_dialog.add_log("➤ " + progress_text)
			
			# 更新进度条
			if progress_text == "Creating temporary build directory...":
				progress_dialog.update_progress(10)
			elif progress_text == "Copying executable...":
				progress_dialog.update_progress(20)
			elif progress_text == "Creating desktop entry...":
				progress_dialog.update_progress(30)
			elif progress_text == "Creating control file...":
				progress_dialog.update_progress(40)
			elif progress_text == "Creating post-install script...":
				progress_dialog.update_progress(50)
			elif progress_text == "Building DEB package...":
				progress_dialog.update_progress(70)
			elif progress_text == "Cleaning up...":
				progress_dialog.update_progress(90)
			elif progress_text == "COMPLETE":
				progress_dialog.update_progress(100)
		else:
			progress_dialog.add_log(line)
	
	# 检查进程是否完成
	if not process_running:
		# 进程已完成，停止计时器
		timer.queue_free()
		
		# 获取退出状态
		var exit_code = OS.get_process_exit_code(progress_dialog.process_id)
		progress_dialog.process_id = -1
		progress_dialog.cancel_btn.disabled = true
		
		# 读取所有剩余输出
		var final_lines = progress_dialog.read_new_output()
		for line in final_lines:
			if line != "":
				progress_dialog.add_log(line)
		
		# 关闭输出文件
		if progress_dialog.output_file != null:
			progress_dialog.output_file.close()
			progress_dialog.output_file = null
		
		# 显示结果
		var result_dialog = AcceptDialog.new()
		result_dialog.title = "Packaging Result"
		
		if exit_code == 0:
			progress_dialog.add_log("✅ Packaging completed successfully!")
			result_dialog.dialog_text = "DEB package created successfully!"
		else:
			progress_dialog.add_log("❌ Packaging failed with error code: " + str(exit_code))
			result_dialog.dialog_text = "Packaging failed!\nError code: " + str(exit_code)
		
		get_editor_interface().get_base_control().add_child(result_dialog)
		result_dialog.popup_centered()
